<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title></title>
  </head>
  <body>
    <div id="app">
      <div>obj: {{ obj }}</div>
    </div>

    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

    <script>
      const { createApp, reactive, watch } = Vue;

      const app = createApp({
        setup() {
          const obj = reactive({ count: 0, someObject: { a: 1, b: 2 } });

          // 1. 会隐式地创建一个深层侦听器 ———— 该回调函数在所有嵌套的变更时都会被触发
          watch(
            obj,
            (newValue, oldValue) => {
              // 在嵌套的属性变更时触发
              // 注意：`newValue` 此处和 `oldValue` 是相等的
              // 因为它们是同一个对象！
              console.log(newValue === oldValue);
            } /*, { deep: true } */
          );
          obj.count++;

          // 2. 错误，因为 watch() 得到的参数是一个 number
          // watch(obj.count, (count) => {});
          // 仅当 obj.count 被改变时触发
          watch(
            // 应该写成返回该属性的 getter 函数
            () => obj.count,
            (count) => {
              console.log("count", count);
            }
          );

          // 3. 仅当 state.someObject 被替换时触发
          // watch(
          //   () => obj.someObject,
          //   () => {}
          // );
          // 原因是依赖收集只收集到 'someObject' 这个key -> effects ，并没有深层收集
          // 需要显示指定 deep 选项，才会递归收集 someObject 对象下面的 key -> effects
          // obj.someObject.a = 111; // 不触发监听器
          // obj.someObject = { c: 333 }; // 触发监听器
          // 如果非要当修改 obj.someObject 原本对象属性的时候触发监听器呢？
          // 可以显式地加上 deep 选项，强制转成深层侦听器，不推荐
          // watch(
          //   () => obj.someObject,
          //   () => {},
          //   { deep: true }
          // );

          return {
            obj,
          };
        },
      });

      app.mount("#app");
    </script>
  </body>
</html>
